﻿using System;

namespace ooWii.IO
{
	/// <summary>
	/// Represents a wild card pattern.
	/// </summary>
	public class Wildcard
	{
		#region Wildcard

		string pattern;

		/// <summary>
		/// Initializes a new instance of the Wildcard class with the specified pattern. 
		/// </summary>
		/// <param name="pattern"></param>
		public Wildcard( string pattern )
		{
			this.pattern = pattern;
		}

		/// <summary>
		/// Indicates whether the pattern specified in the Wildcard constructor finds a match in the input string. 
		/// </summary>
		/// <param name="input">The string to search for a match.</param>
		/// <returns>true if the pattern finds a match; otherwise, false.</returns>
		public bool IsMatch( string input )
		{
			return isMatchSkipAny( input, 0, 0 );
		}

		/// <summary>
		/// Indicates whether the pattern specified in the Wildcard constructor finds a match in the input string starting at the specified input & pattern index, skipping characters in the input string.
		/// </summary>
		/// <param name="input">The string to search for a match.</param>
		/// <param name="inputIndex">The zero-based index at which to start comparing the input.</param>
		/// <param name="patternIndex">The zero-based index at which to start comparing the pattern.</param>
		/// <returns>true if the pattern finds a match; otherwise, false.</returns>
		private bool isMatchSkipAny( string input, int inputIndex, int patternIndex )
		{
			while( inputIndex < input.Length )
			{
				if( isMatch( input, inputIndex, patternIndex ) )
				{
					return true;
				}

				inputIndex++;
			}

			return false;
		}

		/// <summary>
		/// Indicates whether the pattern specified in the Wildcard constructor finds a match in the input string starting at the specified input & pattern index.
		/// </summary>
		/// <param name="input">The string to search for a match.</param>
		/// <param name="inputIndex">The zero-based index at which to start comparing the input.</param>
		/// <param name="patternIndex">The zero-based index at which to start comparing the pattern.</param>
		/// <returns>true if the pattern finds a match; otherwise, false.</returns>
		private bool isMatch( string input, int inputIndex, int patternIndex )
		{
			while( patternIndex < pattern.Length )
			{
				switch( pattern[ patternIndex ] )
				{
				case '?':
					if( inputIndex >= input.Length )
					{
						return false;
					}

					patternIndex++;
					inputIndex++;
					break;

				case '*':
					patternIndex++;

					if( patternIndex < pattern.Length )
					{
						return isMatchSkipAny( input, inputIndex, patternIndex );
					}

					return true;

				default:
					if( inputIndex >= input.Length || Char.ToLowerInvariant( pattern[ patternIndex ] ) != Char.ToLowerInvariant( input[ inputIndex ] ) )
					{
						return false;
					}

					patternIndex++;
					inputIndex++;
					break;
				}
			}

			return true;
		}

		#endregion
	}
}
